﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Shapes;
using Silvermoon.OpenGL;
using System.Drawing;

namespace Silvermoon.Controls.Beta
{
    /// <summary>
    /// Item with image, title and details.
    /// </summary>
    public class TitleDetailsImageListBoxItem : ItemBase
    {
        #region fields
        private ImageShape imageShape;
        private StringShape titleShape;
        private StringShape detailsShape;
        private Margin padding = new Margin(8);
        const int titleDetailsSpace = 2;

        #endregion
        #region ctors/dtors

        public TitleDetailsImageListBoxItem()
            : base()
        {
            imageShape = new ImageShape { Size = new Size(64, 64), UseTextColor = true, Color = Color.Empty };
            titleShape = new StringShape { Alignment = Alignment.Near, LineAlignment = Alignment.Near, LineMode = LineMode.SingleLine };
            detailsShape = new StringShape { Opacity = 200, FontScale = 0.75f, Alignment = Alignment.Near, LineAlignment = Alignment.Near, LineMode = LineMode.WordWrap };

            Shapes.AddRange(imageShape, titleShape, detailsShape);
        }

        public TitleDetailsImageListBoxItem(string title, string details)
            : this()
        {
            this.Title = title;
            this.Details = details;
        }

        public TitleDetailsImageListBoxItem(string title, string details, Texture image)
            : this()
        {
            this.Title = title;
            this.Details = details;
            this.Image = image;
        }

        public TitleDetailsImageListBoxItem(string title)
            : this()
        {
            this.Title = title;
        }

        protected override void Dispose(bool dispose)
        {
            //if (imageShape.Image != null) imageShape.Image.Dispose();
            imageShape.Image = null;
            base.Dispose(dispose);
        }

        #endregion
        #region props

        /// <summary>
        /// Gets or sets the margin of the inner elements.
        /// </summary>
        public Margin Padding
        {
            get { return padding ?? Margin.Empty; }
            set
            {
                if (padding != value)
                {
                    padding = value;
                    OnPaddingChanged();
                }
            }
        }

        public FontSprite Font
        {
            get { return titleShape.Font; }
            set
            {
                if (titleShape.Font != value)
                {
                    titleShape.Font = value;
                    detailsShape.Font = value;
                    OnFontChanged();
                }
            }
        }


        /// <summary>
        /// Gets or sets the title. Title is displayed in a single line.
        /// </summary>
        public string Title
        {
            get { return titleShape.Text ?? string.Empty; }
            set
            {
                if (titleShape.Text != value)
                {
                    titleShape.Text = value;
                    OnTitleChanged();
                }
            }
        }

        /// <summary>
        /// Gets or sets the details. Details is word wrapped if necassary and fills the space under the title.
        /// </summary>
        public string Details
        {
            get { return detailsShape.Text ?? string.Empty; }
            set
            {
                if (detailsShape.Text != value)
                {
                    detailsShape.Text = value;
                    OnDetailsChanged();
                }
            }
        }

        /// <summary>
        /// Gets or sets the image. The image appears at the left.
        /// </summary>
        public Texture Image
        {
            get { return imageShape.Image; }
            set
            {
                if (imageShape.Image != value)
                {
                    imageShape.Image = value;
                    OnImageChanged();
                }
            }
        }

        #endregion
        #region methods

        protected virtual void OnFontChanged()
        {
            Invalidate(InvalidationFlag.LayoutAppearance);
        }

        protected virtual void OnPaddingChanged()
        {
            Invalidate(InvalidationFlag.Layout);
        }

        protected virtual void OnImageChanged()
        {
            Invalidate(InvalidationFlag.Appearance);
        }

        protected virtual void OnDetailsChanged()
        {
            Invalidate(InvalidationFlag.Appearance);
        }

        protected virtual void OnTitleChanged()
        {
            Invalidate(InvalidationFlag.Appearance);
        }

        protected override void OnLayout()
        {
            if (CheckFlag(InvalidationFlag.Size | InvalidationFlag.Layout)) LayoutShapes();
            base.OnLayout();
        }

        private void LayoutShapes()
        {
            Rectangle bounds = padding.Layout(ClientBounds, Size);
            int h = bounds.Height;


            imageShape.Location = Control.ScaledPoint(bounds.X, bounds.Y + 8);
            int x = imageShape.Width + padding.LeftZero;
            int w = Math.Max(0, bounds.Width - x);

            int titleHeight = Title.Length > 0 ? titleShape.Font.CharHeight : 0;
            titleShape.Bounds = Control.ScaledRect(bounds.X + x, bounds.Y, w, titleHeight);
            titleHeight += titleDetailsSpace;
            int dh = Math.Max(0, h - titleHeight);
            detailsShape.Bounds = Control.ScaledRect(bounds.X + x, bounds.Y + titleHeight, w, dh);
        }

        #endregion
    }
}
